package org.javaongems.client.vcl;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;

final public class ControlEvent {
	final static public int MB_LEFT = Event.BUTTON_LEFT;
	final static public int MB_RIGHT = Event.BUTTON_RIGHT;
	final static public int MB_MIDDLE = Event.BUTTON_MIDDLE;

	final static public int SS_SHIFT = 1;
	final static public int SS_ALT = 1 << 1;
	final static public int SS_CTRL = 1 << 2;

	final static public int DS_ENTER = 0;
	final static public int DS_LEAVE = 1;
	final static public int DS_MOVE = 2;
	
	final static public int LI_MOUSE = 0;
	final static public int LI_SHIFT = 1;
	final static public int LI_CLIENTX = 2;
	final static public int LI_CLIENTY = 3;
	final static public int LI_X = 4;
	final static public int LI_Y = 5;
	final static public int LI_KEY = 6;

	final static public int DRAG_THRESHOLD = 5;
	
	private ControlEvent() {
	}
	
	static public Event 	controlEvent;
	static public int		eventType;
	static public Control	targetControl;
	static public Element	targetElement;
	static public int[]		listenerInfo = new int[7];
	
	static public Element dragSourceElement;
	static public Control dragControl;
	static public int dragControlThreshold = -1;
	static public int dragBeginClientX, dragBeginClientY;
	static public boolean dragging, dragMouseDn = false, dragMouseUp = true, dragDropAccepted = false;

	static public void setControlEvent(Event eventWithinExecutionCtx) {
		controlEvent = eventWithinExecutionCtx;
		eventType = DOM.eventGetType(controlEvent);
		targetElement = DOM.eventGetTarget(controlEvent);
		targetControl = targetElement == null ? null : ControlDomRenderer.getGemsControl(targetElement); 
	}
	
	static public void initialiseInfo() {
		listenerInfo[LI_MOUSE] 	= ControlEvent.getMouseState();
		listenerInfo[LI_SHIFT] 	= ControlEvent.getShiftState();
		listenerInfo[LI_CLIENTX] = ControlEvent.getClientX();
		listenerInfo[LI_CLIENTY] = ControlEvent.getClientY();
		listenerInfo[LI_X] 		= listenerInfo[LI_CLIENTX] - DOM.getAbsoluteLeft(ControlEvent.targetElement);
		listenerInfo[LI_Y] 		= listenerInfo[LI_CLIENTY] - DOM.getAbsoluteTop(ControlEvent.targetElement);
		listenerInfo[LI_KEY] 	= DOM.eventGetKeyCode(controlEvent);
		handleDragStateIfRequired();
	}

	static private void handleDragStateIfRequired() {
		if (eventType == Event.ONMOUSEDOWN) { 
			prepareBeginDrag();
		} else if (eventType == Event.ONMOUSEUP) {
			endDrag();
		} else if (eventType == Event.ONMOUSEMOVE) {
			if (!dragging && dragMouseDn) {
				if (dragControl != null) {
					boolean autoMatic  = (dragControl.getDragMode() == Control.DM_AUTO);
					if (dragControl instanceof FormTag) 
						autoMatic = true;
					if (autoMatic) {
						if (dragControlThreshold == -1)
							dragControlThreshold = DRAG_THRESHOLD;
						if (isThresholdExceeded(listenerInfo[LI_CLIENTX], dragBeginClientX, dragControlThreshold)  
							|| isThresholdExceeded(listenerInfo[LI_CLIENTY], dragBeginClientY, dragControlThreshold)) {
							startDrag();
							return;
						}
					}
				}
			}
		} 
		if (!dragging)
			return;
		if (eventType == Event.ONMOUSEMOVE) 
			dragOver(DS_MOVE);
		else if (eventType == Event.ONMOUSEOVER) 
			dragOver(DS_ENTER);
		else if (eventType == Event.ONMOUSEOUT) 
			dragOver(DS_LEAVE);
	}
	
	static void beginAutoDrag() {
		prepareBeginDrag();
		startDrag();
	}
	
	static void beginDrag(boolean immediate, int threshold) {
		if (immediate)
			beginAutoDrag();
		else {
			prepareBeginDrag();
			dragControlThreshold = threshold;
		}
	}
	
	static void startDrag() {
		System.out.println("startDrag [dragging = true]");
		dragging = true;
		dragControl.doStartDrag();
	}
	
	static void endDrag() {
//		System.out.println("endDrag");
		if (dragging)
			dragControl.doEndDrag();
		dragMouseDn = false;
		dragMouseUp = true;
		dragging = false;
	}
	
	static void dragOver(int dragState) {
//		System.out.println("dragOver");
		dragDropAccepted = false;
		dragControl.doDragOver(dragState);
	}
	
	static private void prepareBeginDrag() {
		if (dragging)
			endDrag();
//		System.out.println("prepareBeginDrag [dragging = false]");
		dragSourceElement = targetElement;
		dragBeginClientX = listenerInfo[LI_CLIENTX];
		dragBeginClientY = listenerInfo[LI_CLIENTY];
		dragMouseDn = true;
		dragMouseUp = false;
		dragControl = targetControl;
		dragControlThreshold = -1;
		dragging = false;
	}
	
	static public void clearInfo() {
		for (int i = 0; i < listenerInfo.length; i++) 
			listenerInfo[i] = 0;
	}
	
	static protected boolean isThresholdExceeded(int curr, int prev, int th) {
		return (Math.abs(curr - prev) > th);
	}
	
	static public boolean isLeftDepressed() {
		int mouseButtonsDown = DOM.eventGetButton(controlEvent);
		return ((mouseButtonsDown & Event.BUTTON_LEFT) != 0);
	}
	
	static public boolean isRightDepressed() {
		int mouseButtonsDown = DOM.eventGetButton(controlEvent);
		return ((mouseButtonsDown & Event.BUTTON_RIGHT) != 0);
	}

	static public boolean isMiddleDepressed() {
		int mouseButtonsDown = DOM.eventGetButton(controlEvent);
		return ((mouseButtonsDown & Event.BUTTON_MIDDLE) != 0);
	}
	
	static public boolean isShiftDepressed() {
		return DOM.eventGetShiftKey(controlEvent);
	}

	static public boolean isCtrlDepressed() {
		return DOM.eventGetCtrlKey(controlEvent);
	}
	
	static public boolean isAltDepressed() {
		return DOM.eventGetAltKey(controlEvent);
	}
	
	static public int getClientX() {
		return DOM.eventGetClientX(controlEvent);
	}

	static public int getClientY() {
		return DOM.eventGetClientY(controlEvent);
	}
	
	static public int getShiftState() {
		int ss = 0;
		if (isShiftDepressed())
			ss |= SS_SHIFT;
		if (isCtrlDepressed())
			ss |= SS_CTRL;
		if (isAltDepressed())
			ss |= SS_ALT;
		return ss;
	}
	
	static public int getDragState() {
		return -1;
	}
	
	static public int getMouseState() {
		return DOM.eventGetButton(controlEvent);
	}
}


/* 

	static public Event controlEvent; 
	
	public int DRAG_STATE_ENTER = 0;
	public int DRAG_STATE_LEAVE = 1;
	public int DRAG_STATE_MOVE = 2;
	
	public int SHIFT_STATE_SHIFT = 1;
	public int SHIFT_STATE_ALT = 1 << 1;
	public int SHIFT_STATE_CTRL = 1 << 2;
	
	public int MOUSE_BUTTON_LEFT = Event.BUTTON_LEFT;
	public int MOUSE_BUTTON_RIGHT = Event.BUTTON_RIGHT;
	public int MOUSE_BUTTON_MIDDLE = Event.BUTTON_MIDDLE;

	protected Event gwtEvent;
	
	public int gwtEventType;
	public boolean isShiftDown;
	public boolean isAltDown;
	public boolean isCtrlDown;
	
	public int mouseButtonsDown;
	public boolean isLeftMouseButtonDown;
	public boolean isRightMouseButtonDown;
	public boolean isMiddleMouseButtonDown;
	
	public int clientX, clientY;
	
	public int keyCode;
	
	public Control senderControl;
	public Element senderElement;
	
	public ControlEvent(Event evt) {
		gwtEvent = evt;
		introspectEvent();
	}
	
	static public boolean isControl
	
	protected void introspectEvent() {
		gwtEventType = DOM.eventGetType(gwtEvent); 
		isShiftDown = DOM.eventGetShiftKey(gwtEvent);
		isAltDown = DOM.eventGetAltKey(gwtEvent);
		isCtrlDown = DOM.eventGetCtrlKey(gwtEvent);
		
		mouseButtonsDown = DOM.eventGetButton(gwtEvent);
		
		clientX = DOM.eventGetClientX(gwtEvent);
		clientY = DOM.eventGetClientY(gwtEvent);
		keyCode = DOM.eventGetKeyCode(gwtEvent);
		
		senderElement = DOM.eventGetTarget(gwtEvent);
		if (senderElement != null)
			senderControl = ControlDomRenderer.getGemsControl(senderElement);
	}
	
	public boolean isLeftButtonDepressed() {
		return ((mouseButtonsDown & Event.BUTTON_LEFT) != 0);
	}
	
	public boolean isRightButtonDepressed() {
		return ((mouseButtonsDown & Event.BUTTON_RIGHT) != 0);
	}

	public boolean isMiddleButtonDepressed() {
		return ((mouseButtonsDown & Event.BUTTON_MIDDLE) != 0);
	}


*/